#pragma once
#include "rescue.hpp"
#include <boost/optional.hpp>

class Planner {
public:
	// Plan returns one of the applicable operators
	// to be performed.
	virtual boost::optional<Op> plan(const Rescue&) = 0;
};

// Oracle implements the Planner interface,
// finding the optimal solution as it is given
// the true world up-front.
class Oracle : public Planner {
public:
	Oracle(const Rescue&);
	virtual boost::optional<Op> plan(const Rescue&);
private:
	std::vector<Op> ops;
};

class DepthFirst : public Planner {
public:
	virtual boost::optional<Op> plan(const Rescue&);
private:
	bool havetime(const Rescue&, boost::optional<Op>);
};


class Hindsight : public Planner {
public:
	Hindsight(unsigned int, unsigned int, bool reuse=true);

	virtual boost::optional<Op> plan(const Rescue&);

private:
	// If reuse is true then samples are reused if
	// possible.
	bool reuse;

	// N is the number of sampled futures.
	unsigned int N;

	// S is the size of each sample.
	unsigned int S;

	// Last is the last world, from which the futures
	// were generated.
	Rescue last;

 	// Futures are the current futures, consistent with
	// the last map.
	std::vector<Rescue> futures;
};

// Sim simulates a robot moving in the given world using the
// given planner to chose its next action. If dump is true then
// an image is dumpped after each action is performed.
void sim(Rescue, Planner*, bool dump = false);
